<?php
// +----------------------------------------------------------------------
// | A3Mall
// +----------------------------------------------------------------------
// | Copyright (c) 2020 http://www.a3-mall.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: xzncit <158373108@qq.com>
// +----------------------------------------------------------------------

namespace app\common\model\users;

use app\common\model\base\A3Mall;
use app\common\model\Calculation;
use app\common\model\system\UsersLog;
use think\Exception;

class Users extends A3Mall{
    // 余额保留小数点位数
    const AMOUNT_SCALE = 20;

    /**
     * 服务费收取状态
     */
    const HAS_SERVICE_CHARGE_LIST = [
        'OPEN'  => 1,   // 收取服务费
        'CLOSE' => 2,   // 免服务费
    ];

    // 消费类型列表
    const CONSUME_TYPE_LIST = [
        'SERVICE_CHARGE'    => 'SERVICE_CHARGE',    //服务费
        'VIP_RENEW' => 'VIP_RENEW', // vip 激活
    ];

    const MONITOR_BALANCE_MIN = 10;  // 允许监控的最少余额

    protected $type = [
        "id"=>"integer",
        "issue_group_id"=>"integer",
        "accept_group_id"=>"integer",
        "birthday"=>"integer",
        "sex"=>"integer",
        "exp"=>"integer",
        "point"=>"integer",
        "status"=>"integer",
        "is_spread"=>"integer",
        "spread_id"=>"integer",
        "spread_time"=>"integer",
        "pay_count"=>"integer",
        "spread_count"=>"integer",
        "amount"=>"float",
        "spread_amount"=>"float",
        "create_time"=>"integer",
        "last_login"=>"integer"
    ];

    /**
     * 获取 vip 套餐列表
     */
    static function vipPackage() {
        $list = [
            'monthly'   => [
                'type'  => 1,   // 月份激活
                'money' => 15,  // 单价
            ],
            'permanent' => [
                'type'  => 2,   // 永久激活
                'money' => 150, // 价格
            ],
        ];
        return $list;
    }


    /**
     * 计算有效期
     * @param $vipExpire
     * @param $type
     * @return string
     */
    static function vipExpireCalculation($vipExpire,$type) {
        $nowTime = time();
        $vipExpire = $vipExpire > $nowTime?$vipExpire:$nowTime;
        $vipPackageList = self::vipPackage();
        $vipPackageList = array_combine(array_column($vipPackageList,'type'),array_keys($vipPackageList));
        switch ($vipPackageList[$type]) {
            case 'monthly':     // 按月添加
                $vipExpire = Calculation::strtotimeCustom('+1 month',$vipExpire);
                break;
            case 'permanent':   // 永久激活
                $vipExpire = 0;
                break;
            default:
                throw new Exception('会员套餐类型不存在');
        }
        return $vipExpire;
    }


    /**
     * 判断用户是否为vip
     * @param array $params 需要字段：vip、vip_expire
     * @return bool
     */
    static function isVip(array $params) {
        if($params['vip'] < 1 || ($params['vip_expire'] > 0 && time() > $params['vip_expire'])) {
            return false;
        }
        return true;
    }

    /**
     * 获取余额最小限制
     * @param array $params 需要字段 has_service_charge
     */
    static function balanceMinLimit(array $params) {
        return self::hasServiceCharge($params['has_service_charge'])?self::MONITOR_BALANCE_MIN:0;
    }

    /**
     * 判断是否需要收取服务费
     * @param $hasServiceCharge
     * @return bool
     */
    static function hasServiceCharge($hasServiceCharge) {
        return $hasServiceCharge == self::HAS_SERVICE_CHARGE_LIST['OPEN']?true:false;
    }

    /**
     * 判断是否允许监控买卖
     * @param array $params 需要字段：vip、vip_expire、has_service_charge、local_balance
     */
    static function isMonitor(array $params) {
        if(!self::isVip($params)) {
            return false;
        }
        // 判断余额与最小服务费限额
        if(bccomp($params['local_balance'],self::balanceMinLimit($params),self::AMOUNT_SCALE) == -1) {
            return false;
        }
        return true;
    }


    /**
     * vip 续费
     * @param $details 用户详情，需要字段[id,vip,vie_expire,local_balance,local_consume]
     * @param $type 续费类型，按 vipPackage 包中的类型
     * @param $money 会员费用
     */
    public function vipRenew($details,$type,$money) {
        $updateData = [
            'vip'   => 1,
            'vip_expire'    => self::vipExpireCalculation($details['vip_expire'],$type)
        ];
        // 更新数据
        if(!self::recordUpdate([
            'id'    => $details['id'],
            'vip'   => $details['vip'],
            'vip_expire'   => $details['vip_expire'],
        ],$updateData)) {
            return false;
        }

        // 添加消费记录
        if(!$this->consume($details,$money,self::CONSUME_TYPE_LIST['VIP_RENEW'],0,sprintf('Valid from %s to %s',$details['vip_expire'],$updateData['vip_expire']))) {
            return false;
        }

        return true;
    }


    /**
     * 修改vip状态
     * @param $details 用户详情，需字段[id,username,vip,vip_expire]
     * @param $vip vip 等级；0 为关闭vip
     * @return bool
     */
    public function changeVipStatus($details,$vip) {
        $updateData = [
            'vip'   => $vip,
        ];
        if($updateData['vip'] && $details['vip_expire'] != 0) {
            $updateData['vip_expire'] = 0;
        }

        // 更新数据
        if(!self::recordUpdate([
            'id'    => $details['id'],
            'vip'   => $details['vip'],
            'vip_expire'    => $details['vip_expire'],
        ],$updateData)) {
            return false;
        }
        // 添加日志
        UsersLog::logAdd($updateData['vip']?'VIP_OPEN':'VIP_CLOSE',array_merge($details,[
            'vip_expire_new'    => array_key_exists('vip_expire',$updateData)?$updateData['vip_expire']:$details['vip_expire']
        ]),$details['id']);
        return true;
    }


    /**
     * 修改是否收取手续费
     * @param $details 用户详情
     * @param $serviceChargeStatus 是否收取手续费
     * @param $serviceChargeRate 服务费率
     * @return bool
     */
    public function changeServiceCharge($details,$serviceChargeStatus,$serviceChargeRate) {
        $updateData = [
            'has_service_charge'   => $serviceChargeStatus,
            'service_charge_rate'   => $serviceChargeRate,
        ];

        // 更新数据
        if(!self::recordUpdate([
            'id'    => $details['id'],
            'has_service_charge'   => $details['has_service_charge'],
            'service_charge_rate'   => $details['service_charge_rate'],
        ],$updateData)) {
            return false;
        }
        // 添加日志
        UsersLog::logAdd('SERVICE_CHARGE',array_merge($details,$updateData),$details['id']);
        return true;
    }

    /**
     * 充值或提现
     * @param $details 用户详情，需要字段[id,username,local_amount,local_balance]
     * @param $amount 充值金额
     */
    public function recharge($details,$amount) {
        $isRecharge = bccomp($amount,0,self::AMOUNT_SCALE)  == -1?false:true;
        $updateData = [
            'local_amount'  => Calculation::decimal(bcadd($details['local_amount'],$amount,self::AMOUNT_SCALE)),
            'local_balance'  => Calculation::decimal(bcadd($details['local_balance'],$amount,self::AMOUNT_SCALE)),
        ];
        // 更新数据
        if(!self::recordUpdate([
            'id'    => $details['id'],
            'local_amount'   => $details['local_amount'],
            'local_balance'   => $details['local_balance'],
        ],$updateData)) {
            return false;
        }

        // 添加充值详情日志
        if(!$accountDetailsId = AccountDetails::recordAdd(bccomp($amount,0,self::AMOUNT_SCALE) == -1?'ADMIN_WITHDRAWAL':'ADMIN_RECHARGE',$details['id'],$amount)) {
            return false;
        }

        // 添加日志
        UsersLog::logAdd($isRecharge?'RECHARGE':'WITHDRAWAL',array_merge($details,['money'=>abs($amount)]),$accountDetailsId);
        return true;
    }



    /**
     * 用户余额消费
     * @param $details 用户详情
     * @param $amount    消费金额 【填写正数】
     * @param string $type  消费类型
     * @param int $relationId 详细关联ID
     * @param string 费用说明
     * @return bool 执行情况
     */
    public function consume($details,$amount,string $type,$relationId = null,$explain = null) {
        if(bccomp($amount,0,self::AMOUNT_SCALE) == -1) {
            $amount = bcsub(0,$amount,self::AMOUNT_SCALE);
        }
        // 判断消费金额不能大于现有金额
        if(bccomp($details['local_balance'],$amount,self::AMOUNT_SCALE) == -1) {
            return false;
        }

        $updateData = [
            'local_balance'  => Calculation::decimal(bcsub($details['local_balance'],$amount,self::AMOUNT_SCALE)),
            'local_consume'  => Calculation::decimal(bcadd($details['local_consume'],$amount,self::AMOUNT_SCALE)),
        ];
        // 更新数据
        if(!self::recordUpdate([
            'id'    => $details['id'],
            'local_balance'   => $details['local_balance'],
            'local_consume'   => $details['local_consume'],
        ],$updateData)) {
            return false;
        }
        $extraParams = [
            'relation_id'   => empty($relationId)?0:$relationId,
        ];
        if(!is_null($explain)) {
            $extraParams['explain'] = $explain;
        }
        // 添加消费详情记录
        if(!AccountDetails::recordAdd($type,$details['id'],bcsub(0,$amount,self::AMOUNT_SCALE),$extraParams)) {
            return false;
        }
        return true;
    }

    /**
     * 更新数据
     * @param $where 条件
     * @param $update 更新内容
     * @return Users|void 返回已更新的数量
     */
    static function recordUpdate($where,$update) {
        $result = self::update($update,$where);
        return $result?$result->getNumRows():0;
    }

    public function levelimit(){
        return $this->hasOne(AccountLevelLimit::class,'user_id','id')
            ->joinType("LEFT");
    }

    public function getList($condition=[],$size=10){
        $count = $this->withJoin("levelimit")->where($condition)->count();
        $data = $this->withJoin("levelimit")->where($condition)->order('users.id desc')->paginate($size);
//        $count = $this->where($condition)->count();
//        $data = $this->where($condition)->order('id desc')->paginate($size);

        $list = array_map(function ($res){
            $res['time'] = $res->create_time;
            return $res;
        },$data->items());

        return [
            "count"=>$count,
            "data"=>$list
        ];
    }

    public function getCreateTimeAttr($value){
        return date("Y-m-d H:i:s",$value);
    }

    public function setUsernameAttr($value){
        return strip_tags(trim($value));
    }

    public function setPasswordAttr($value){
        return strip_tags(trim($value));
    }

    public function setEmailAttr($value){
        return strip_tags(trim($value));
    }

    public function setAvatarAttr($value){
        return strip_tags(trim($value));
    }

    public function setNicknameAttr($value){
        return strip_tags(trim($value));
    }

    public function setRealnameAttr($value){
        return strip_tags(trim($value));
    }

    public function setMobileAttr($value){
        return strip_tags(trim($value));
    }

    public function setCreateIpAttr($value){
        return strip_tags(trim($value));
    }

    public function setLastIpAttr($value){
        return strip_tags(trim($value));
    }

    //获取id到用户名的映射
    public static function getIdUserNameList($id)
    {
        if(is_array($id)){
            $query=static::whereIn('id',$id);
        }else{
            $query=static::where('id',$id);
        }
        return $query->column('username', 'id');
    }

    public function getAmountAttr($value){
        return sprintf('%.2f',$value);
    }

}
